package fi.internetix.ck;

import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class HTMLNodePrinter extends DefaultNodePrinter {
  
  public void processNode(Node node, StringBuilder output) {
    if (!invisibleElement(node)) {
      super.processNode(node, output);
    }
  }

  public void processAttribute(Element element, Node attribute, StringBuilder output) {
    String attrName = NodePrinterUtils.extractLowercaseTagName(attribute.getNodeName());
    if (stripAttributes.contains(attrName) || attrName.startsWith("on")) {
      return;
    }
    String attrValue = attribute.getNodeValue();
    if (attrName.equals("style")) {
      attrValue = cleanupStyleAttribute(attrValue);
    }
    if (attrValue != null) {
      output.append(' ');
      output.append(attrName);
      output.append("=\"");
      output.append(attrValue);
      output.append("\"");
    }
  }

  private String cleanupStyleAttribute(String value) {
    StringBuilder styleBuilder = new StringBuilder();
    StringTokenizer st = new StringTokenizer(value, ";", false);
    while (st.hasMoreTokens()) {
      String[] s = st.nextToken().split(":"); 
      if (s.length == 2) {
    	String attrName = s[0].trim();
	    if (isAllowedStyle(attrName)) {
	      styleBuilder.append(attrName);
	      styleBuilder.append(':');
	      styleBuilder.append(s[1].trim());
	      styleBuilder.append(';');
	    }
      }
    }
    return styleBuilder.length() > 0 ? styleBuilder.toString() : null;
  }
  
  private boolean invisibleElement(Node n) {
    Node styleAttr = n.getAttributes().getNamedItem("style");
    if (styleAttr != null) {
      String attrValue = styleAttr.getNodeValue();
      if (attrValue.matches("(?is).*?(visibility|display)\\s*:\\s*(hidden|none).*?")) {
        return true;
      }
      
    }
    return false;
  }

  private boolean isAllowedStyle(String style) {
    return allowedStyles.contains(style.toLowerCase());
  }

  private static final Set<String> allowedStyles = new HashSet<String>();
  private static final Set<String> stripAttributes = new HashSet<String>();
  
  static {
    allowedStyles.add("color");
    allowedStyles.add("direction");
    allowedStyles.add("text-align");
    allowedStyles.add("vertical-align");
    allowedStyles.add("background-color");
    allowedStyles.add("border");
    allowedStyles.add("border-style");
    allowedStyles.add("border-width");
    allowedStyles.add("border-color");
    allowedStyles.add("border-bottom");
    allowedStyles.add("border-bottom-color");
    allowedStyles.add("border-bottom-style");
    allowedStyles.add("border-bottom-width");
    allowedStyles.add("border-top");
    allowedStyles.add("border-top-color");
    allowedStyles.add("border-top-style");
    allowedStyles.add("border-top-width");
    allowedStyles.add("border-left");
    allowedStyles.add("border-left-color");
    allowedStyles.add("border-left-style");
    allowedStyles.add("border-left-width");
    allowedStyles.add("border-right");
    allowedStyles.add("border-right-color");
    allowedStyles.add("border-right-style");
    allowedStyles.add("border-right-width");
    allowedStyles.add("font-style");
    allowedStyles.add("font-weight");
    allowedStyles.add("text-decoration");
    
    stripAttributes.add("id");
    stripAttributes.add("class");
    stripAttributes.add("lang");
  }

}
